package linuxbox.common;

import java.io.*;
import java.util.*;

import org.apache.log4j.*;

import org.jdom.*;
import org.jdom.input.*;

import org.apache.commons.digester.*;
import org.apache.commons.digester.xmlrules.*;

import linuxbox.BoxStatic;
import linuxbox.exception.*;
import linuxbox.util.*;

import com.thebox.config.*;

public class BoxInit {
    protected static Logger logger = Logger.getLogger(BoxInit.class.getName());
    static {
        logger.setLevel(Level.DEBUG);
        logger.addAppender(new ConsoleAppender(
            new PatternLayout("%5p (%F:%L) - %m%n")));
    }
    protected String mainConf = null;

    public static BoxInit getInstance(String fn, String home) {
        BoxStatic.HOME_DIR = home;
        BoxStatic.configPath = BoxStatic.HOME_DIR + BoxStatic.webInfPath + File.separator;
        BoxInit ret = new BoxInit(fn);
        return ret;
    }

    private BoxInit(String fn) {
        mainConf = fn;
    }

    public void initSystem() {
        try {
            String configFile = BoxStatic.configPath + mainConf;
            //String configFile = "c:/project/thebox/boxconf/WEB-INF/main.xml";

            SAXBuilder builder = new SAXBuilder(false);
            Document doc = builder.build(new FileInputStream(configFile));
            Element root = doc.getRootElement();

            List props = root.getChildren("Property");
            Map nameValues = new HashMap();
            for (Iterator it = props.iterator(); it.hasNext(); ) {
                Element p = (Element)it.next();
                String name = p.getAttributeValue("name");
                String value = p.getTextTrim();
                if (name != null && value != null) {
                    nameValues.put(name.trim().toUpperCase(), value);
                } else {
                    throw new Exception("missing name value:" + name + ":" + value);
                }
            }

            BoxStatic.contextName = (String)nameValues.get("ContextName".toUpperCase());
            if (BoxStatic.contextName != null && BoxStatic.contextName.length() > 0)
            {
              BoxStatic.jspDir =  "/" + BoxStatic.contextName + "/" + BoxStatic.defaultLang + "/jsp/";
              BoxStatic.servletDir =  "/" + BoxStatic.contextName + BoxStatic.servletPath + "/";
              BoxStatic.imageDir =  "/" + BoxStatic.contextName + "/" + BoxStatic.defaultLang + "/images/";
              BoxStatic.cssDir =  "/" + BoxStatic.contextName + "/" + BoxStatic.defaultLang + "/css/";
            }
            else
            {
              BoxStatic.jspDir =  "/" + BoxStatic.defaultLang + "/jsp/";
              BoxStatic.servletDir =  BoxStatic.servletPath + "/";
              BoxStatic.imageDir =  "/" + BoxStatic.defaultLang + "/images/";
              BoxStatic.cssDir =  "/" + BoxStatic.defaultLang + "/css/";
            }


            BoxStatic.noUserJSP = (String)nameValues.get("NoUserJSP".toUpperCase());
            BoxStatic.errorJSP = (String)nameValues.get("ErrorJSP".toUpperCase());
            BoxStatic.timeoutJSP = (String)nameValues.get("TimeoutJSP".toUpperCase());
            BoxStatic.accessRightErrorJSP = (String)nameValues.get("AccessRightErrorJSP".toUpperCase());
            BoxStatic.PRINT_STACK_TRACE = "true".equalsIgnoreCase((String)nameValues.get("StackTrace".toUpperCase()));
            BoxStatic.DOWNLOAD_FILE_DIR = (String)nameValues.get("DownloadFileDir".toUpperCase());
            BoxStatic.defaultLang = (String)nameValues.get("DefaultLanguage".toUpperCase());
            BoxStatic.dbUrl = (String)nameValues.get("db_url".toUpperCase());
            BoxStatic.dbDriver = (String)nameValues.get("db_drv".toUpperCase());
            BoxStatic.username = (String)nameValues.get("username".toUpperCase());
            BoxStatic.password = (String)nameValues.get("password".toUpperCase());

            String formatXML = (String)nameValues.get("FormatXML".toUpperCase());
            if ((formatXML != null) && (formatXML.trim().length() > 0)) {
                BoxStatic.formater = new BoxFormat(BoxStatic.HOME_DIR
                    + BoxStatic.webInfPath + File.separator + formatXML);
            } else {
                throw new Exception("missing format xml");
            }

            String errMsgXML = (String)nameValues.get("ErrMsgXML".toUpperCase());
            if ((errMsgXML != null) && (errMsgXML.trim().length() > 0)) {
                BoxStatic.excHelper = new ExceptionHelper(BoxStatic.HOME_DIR
                    + BoxStatic.webInfPath + File.separator + errMsgXML);
            } else {
                throw new Exception("missing errmsg xml");
            }

            //Before config the log4j, everythis goes to rootLogger,
            //After, goes to where the configs specified.
            // if the log4j-init-file is not set, then no point in trying
            String logInitFile = (String)nameValues.get("Log4jInitFile".toUpperCase());
            if ((logInitFile != null) && (logInitFile.trim().length() > 0)) {
                logInitFile = BoxStatic.configPath + logInitFile;
                //You can dynamically change the config value, the default is 60 seconds to refresh
                //TODO: how to set the log file location in the config file
                PropertyConfigurator.configureAndWatch(logInitFile);
            } else {
                throw new Exception("No Log4J config file found!");
            }

            // init Connection Pool
            BoxStatic.cPool = ConnectionPool.getInstance();

            if (logger.isDebugEnabled())
            {
              logger.debug("BoxStatic.HOME_DIR="+BoxStatic.HOME_DIR);
              logger.debug("BoxStatic.contextName="+BoxStatic.contextName);
              logger.debug("BoxStatic.jspDir="+BoxStatic.jspDir);
              logger.debug("BoxStatic.servletDir="+BoxStatic.servletDir);
              logger.debug("BoxStatic.imageDir="+BoxStatic.imageDir);
              logger.debug("BoxStatic.cssDir="+BoxStatic.cssDir);
              logger.debug("NoUserJSP is " + BoxStatic.noUserJSP);
              logger.debug("ErrorJSP is " + BoxStatic.errorJSP);
              logger.debug("TimeoutJSP is " + BoxStatic.timeoutJSP);
              logger.debug("PRINT_STACK_TRACE is " + BoxStatic.PRINT_STACK_TRACE);
            }

            // prepare ModuleControl
            Element moduleDef = root.getChild("ActionChannels");
            //BoxStatic.moduleControl = new ModuleControl(moduleDef);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void zInitSystem() throws Exception {
        String configFile = BoxStatic.configPath + mainConf;
        //String configFile = "c:/project/thebox/boxconf/WEB-INF/main.xml";

        String ruleFile = BoxStatic.configPath + "/digester/MainConfigRule.xml";

        File input = new File(configFile);
        File rules = new File(ruleFile);

        logger.debug("input path: " + input.getPath());
        String inputPath = input.getAbsoluteFile().getParent();
        logger.debug("input path parent: " + inputPath);
        String rulesPath = rules.getAbsoluteFile().getParent();
        logger.debug("rules path parent: " + rulesPath);

        Digester digester = DigesterLoader.createDigester(rules.toURI().toURL());

        MainConfig mc = (MainConfig)digester.parse(input);
        if (mc != null) {
            mc.setPath(inputPath, rulesPath);
            mc.loadModule();
            //logger.debug(mc.toString());
        } else {
            logger.debug("get a null MainConfig ref");
        }

        //BoxConfig bc = (BoxConfig)digester.parse(input);
        //print(bc.toString());

        Map propMap = mc.getPropMap();
        BoxStatic.contextName = (String)propMap.get("ContextName".toUpperCase());
        if (BoxStatic.contextName != null && BoxStatic.contextName.length() > 0) {
            BoxStatic.jspDir =  "/" + BoxStatic.contextName + "/" 
                + BoxStatic.defaultLang + "/jsp/";
            BoxStatic.servletDir =  "/" + BoxStatic.contextName 
                + BoxStatic.servletPath + "/";
            BoxStatic.imageDir =  "/" + BoxStatic.contextName + "/" 
                + BoxStatic.defaultLang + "/images/";
            BoxStatic.cssDir =  "/" + BoxStatic.contextName + "/" 
                + BoxStatic.defaultLang + "/css/";
        } else {
            BoxStatic.jspDir =  "/" + BoxStatic.defaultLang + "/jsp/";
            BoxStatic.servletDir =  BoxStatic.servletPath + "/";
            BoxStatic.imageDir =  "/" + BoxStatic.defaultLang + "/images/";
            BoxStatic.cssDir =  "/" + BoxStatic.defaultLang + "/css/";
        }

        BoxStatic.noUserJSP = (String)propMap.get("NoUserJSP".toUpperCase());
        BoxStatic.errorJSP = (String)propMap.get("ErrorJSP".toUpperCase());
        BoxStatic.timeoutJSP = (String)propMap.get("TimeoutJSP".toUpperCase());
        BoxStatic.accessRightErrorJSP = (String)propMap.get
            ("AccessRightErrorJSP".toUpperCase());
        BoxStatic.PRINT_STACK_TRACE = "true".equalsIgnoreCase
            ((String)propMap.get("StackTrace".toUpperCase()));
        BoxStatic.DOWNLOAD_FILE_DIR = (String)propMap.get("DownloadFileDir".toUpperCase());
        BoxStatic.defaultLang = (String)propMap.get("DefaultLanguage".toUpperCase());
        BoxStatic.dbUrl = (String)propMap.get("db_url".toUpperCase());
        BoxStatic.dbDriver = (String)propMap.get("db_drv".toUpperCase());
        BoxStatic.username = (String)propMap.get("username".toUpperCase());
        BoxStatic.password = (String)propMap.get("password".toUpperCase());

        String formatXML = (String)propMap.get("FormatXML".toUpperCase());
        if ((formatXML != null) && (formatXML.trim().length() > 0)) {
            BoxStatic.formater = new BoxFormat(BoxStatic.HOME_DIR
                                               + BoxStatic.webInfPath 
                                               + File.separator + formatXML);
        } else {
            throw new Exception("missing format xml");
        }

        String errMsgXML = (String)propMap.get("ErrMsgXML".toUpperCase());
        if ((errMsgXML != null) && (errMsgXML.trim().length() > 0)) {
            BoxStatic.excHelper = new ExceptionHelper(BoxStatic.HOME_DIR
                                                      + BoxStatic.webInfPath 
                                                      + File.separator + errMsgXML);
        } else {
            throw new Exception("missing errmsg xml");
        }

        //Before config the log4j, everythis goes to rootLogger,
        //After, goes to where the configs specified.
        // if the log4j-init-file is not set, then no point in trying
        String logInitFile = (String)propMap.get("Log4jInitFile".toUpperCase());
        if ((logInitFile != null) && (logInitFile.trim().length() > 0)) {
            logInitFile = BoxStatic.configPath + logInitFile;
            // You can dynamically change the config value, the default 
            // is 60 seconds to refresh
            // TODO: how to set the log file location in the config file
            PropertyConfigurator.configureAndWatch(logInitFile);
        } else {
            throw new Exception("No Log4J config file found!");
        }

        // init Connection Pool
        BoxStatic.cPool = ConnectionPool.getInstance();

        if (logger.isDebugEnabled()) {
            logger.debug("BoxStatic.HOME_DIR="+BoxStatic.HOME_DIR);
            logger.debug("BoxStatic.contextName="+BoxStatic.contextName);
            logger.debug("BoxStatic.jspDir="+BoxStatic.jspDir);
            logger.debug("BoxStatic.servletDir="+BoxStatic.servletDir);
            logger.debug("BoxStatic.imageDir="+BoxStatic.imageDir);
            logger.debug("BoxStatic.cssDir="+BoxStatic.cssDir);
            logger.debug("NoUserJSP is " + BoxStatic.noUserJSP);
            logger.debug("ErrorJSP is " + BoxStatic.errorJSP);
            logger.debug("TimeoutJSP is " + BoxStatic.timeoutJSP);
            logger.debug("PRINT_STACK_TRACE is " + BoxStatic.PRINT_STACK_TRACE);
        }
            
        // prepare ModuleControl
        //Element moduleDef = root.getChild("ActionChannels");
        //BoxStatic.moduleControl = new ModuleControl(moduleDef);
        BoxStatic.mainConfig = mc;
    }

    public static void main(String[] args) {
        try {
            //BoxInit.initTestEnv();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void log(String str) {
        System.out.println(str);
    }
}